from enum import auto
from typing import List, Callable

import pygame
from pygame.locals import *

from Lib.Core.Scene import Scene
from Lib.Core.Typing import LowEnum


class UILayer(LowEnum):
    TOP = auto()
    MID = auto()
    BOT = auto()
    SYS = auto()
    OTHER = auto()


class Game:
    def __init__(self):
        from constants import config
        pygame.init()
        self.screen = None
        self.scene: [Scene] = None
        self.is_running = True
        self.clock = pygame.time.Clock()
        self.fps = int(config.get("base", "fps"))

        self.list_update: List[Callable] = []
        # 鼠标事件
        self.list_mouse_button_down: List[Callable] = []
        self.list_mouse_button_up: List[Callable] = []
        self.list_mouse_motion: List[Callable] = []
        self.list_mouse_wheel: List[Callable] = []

        # 键盘事件
        self.list_key_down: List[Callable] = []
        self.list_key_up: List[Callable] = []

        self.ui_group = pygame.sprite.LayeredUpdates()

    def SetMode(self, window_size):
        self.screen = pygame.display.set_mode(window_size, 0, 32)
        from constants import config
        pygame.display.set_caption(f"{config.get('base', 'game_name')} {config.get('base', 'version')}")
        if config.get('base', 'game_icon'): pygame.display.set_icon(config.get('base', 'game_icon'))
        return self

    def Run(self):
        import locals
        while self.is_running:
            tick = self.clock.tick(self.fps)
            self.screen.fill([0, 0, 0])
            if self.scene and self.screen:
                self.scene.update(tick)
                self.scene.draw(self.screen)

            for event in pygame.event.get():
                if event.type == QUIT:
                    self.Exit()
                # 鼠标事件
                if event.type == MOUSEBUTTONDOWN or event.type == MOUSEBUTTONUP or event.type == MOUSEMOTION:
                    if event.type == MOUSEBUTTONDOWN:
                        [action_mouse_button_down(event.pos, event.button) for action_mouse_button_down in
                         self.list_mouse_button_down]
                    if event.type == MOUSEBUTTONUP:
                        [action_mouse_button_up(event.pos, event.button) for action_mouse_button_up in
                         self.list_mouse_button_up]
                    if event.type == MOUSEMOTION:
                        from Lib import UtilsGame
                        for ui_base in locals.list_ui_collide['bot'] \
                                       + locals.list_ui_collide['mid'] \
                                       + locals.list_ui_collide['top'] \
                                       + locals.list_ui_collide['sys']:
                            ui = UtilsGame.CheckClick(ui_base, ui_base.rect, event.pos)
                            if ui:
                                locals.mouse_move_focus_ui = ui
                                for sprite in ui.sprites():
                                    if sprite.rect.collidepoint(event.pos[0], event.pos[1]):
                                        locals.mouse_move_focus_sprite = sprite
                            else:
                                locals.mouse_move_focus_ui = None
                                locals.mouse_move_focus_sprite = None
                        [action_mouse_motion(event.pos) for action_mouse_motion in self.list_mouse_motion]
                    if event.type == MOUSEWHEEL:
                        # print(event)
                        # print(event.x, event.y)
                        # print(event.flipped)
                        # print(event.which)
                        [action_mouse_wheel(event) for action_mouse_wheel in self.list_mouse_wheel]
                # 键盘事件
                if event.type == KEYDOWN or event.type == KEYUP:
                    if event.type == KEYDOWN:
                        [key_down(event) for key_down in self.list_key_down]
                    if event.type == KEYUP:
                        [key_up(event) for key_up in self.list_key_up]

            # 主事件
            [action_update(tick) for action_update in self.list_update]
            if self.ui_group:
                self.ui_group.update(tick)
                self.ui_group.draw(self.screen)

            # print(len(self.list_mouse_button_down))
            # print(len(self.list_mouse_button_up))
            # print(len(self.list_mouse_motion))
            # print(len(self.list_update))
            # print(len(constants.list_ui))
            # print(self.list_mouse_button_up)
            # print(self.list_mouse_motion)
            # print(self.list_update)
            pygame.display.update()

    def Exit(self):
        import sys
        sys.exit()
